import dataManager from './dataManager';

// Find components upward
function findComponentUpward(context, componentName, componentNames) {
  if (typeof componentName === 'string') {
    componentNames = [componentName];
  } else {
    componentNames = componentName;
  }

  let parent = context.$parent;
  let name = parent.$options.name;
  while (parent && (!name || componentNames.indexOf(name) < 0)) {
    parent = parent.$parent;
    if (parent) name = parent.$options.name;
  }
  return parent;
}
export { findComponentUpward };

// Find component downward
export function findComponentDownward(context, componentName) {
  const childrens = context.$children;
  let children = null;

  if (childrens.length) {
    for (const child of childrens) {
      const name = child.$options.name;
      if (name === componentName) {
        children = child;
        break;
      } else {
        children = findComponentDownward(child, componentName);
        if (children) break;
      }
    }
  }
  return children;
}

// Find components downward
export function findComponentsDownward(context, componentName) {
  return context.$children.reduce((components, child) => {
    if (child.$options.name === componentName) components.push(child);
    const foundChilds = findComponentsDownward(child, componentName);
    return components.concat(foundChilds);
  }, []);
}

// Find components upward
export function findComponentsUpward(context, componentName) {
  let parents = [];
  if (context.$parent) {
    if (context.$parent.$options.name === componentName) parents.push(context.$parent);
    return parents.concat(findComponentsUpward(context.$parent, componentName));
  } else {
    return [];
  }
}

// Find brothers components
export function findBrothersComponents(context, componentName) {
  let res = context.$parent.$children.filter(item => {
    return item.$options.name === componentName;
  });
  let index = res.indexOf(context);
  res.splice(index, 1);
  return res;
}

function typeOf(obj) {
  const toString = Object.prototype.toString;
  const map = {
    '[object Boolean]': 'boolean',
    '[object Number]': 'number',
    '[object String]': 'string',
    '[object Function]': 'function',
    '[object Array]': 'array',
    '[object Date]': 'date',
    '[object RegExp]': 'regExp',
    '[object Undefined]': 'undefined',
    '[object Null]': 'null',
    '[object Object]': 'object',
  };
  return map[toString.call(obj)];
}

// deepCopy
export function deepCopy(data) {
  const t = typeOf(data);
  let o;

  if (t === 'array') {
    o = [];
  } else if (t === 'object') {
    o = {};
  } else {
    return data;
  }

  if (t === 'array') {
    for (let i = 0; i < data.length; i++) {
      o.push(deepCopy(data[i]));
    }
  } else if (t === 'object') {
    for (let i in data) {
      o[i] = deepCopy(data[i]);
    }
  }
  return o;
}

// deepSeal
export function deepSeal(obj) {
  Object.seal(obj); // 首先密封第一层对象
  for (let key in obj) {
    let prop = obj[key];
    if (!obj.hasOwnProperty(key) || !(typeof prop === 'object') || Object.isSealed(prop)) {
      continue; // 不是自有属性或者属性不为对象或者属性已经密封，则跳过当前循环。
    }
    deepSeal(prop); // 密封对象
  }
  return obj;
}

// deepFreeze
export function deepFreeze(obj) {
  Object.freeze(obj); // 首先冻结第一层对象
  for (let key in obj) {
    let prop = obj[key];
    if (!obj.hasOwnProperty(key) || !(typeof prop === 'object') || Object.isFrozen(prop)) {
      continue; // 不是自有属性或者属性不为对象或者属性已经冻结，则跳过当前循环。
    }
    deepFreeze(prop); // 冻结对象
  }
  return obj;
}

// debounds
export function debounds(fun, delay) {
  let last = null;
  return function(...args) {
    const ctx = this;
    if (last) clearTimeout(last);
    last = setTimeout(function() {
      fun.apply(ctx, args);
    }, delay);
  };
}

// throttle
export function throttle(fun, delay) {
  let last = 0;
  return function(...args) {
    let cur = new Date();
    if (cur - last > delay) {
      fun.apply(this, args);
      last = cur;
    }
  };
}

// 分页计算
export function computedPageData(totalData, pageIndex) {
  let pageData = [];
  for (var key in totalData) {
    key++;
    if (+key <= pageIndex * 10 && +key >= pageIndex * 10 - 9) {
      pageData.push(totalData[key - 1]);
    }
  }
  return pageData;
}

// 时间戳转日期格式
export function getLocalTime(nS) {
  // 时间戳是10位的时候要*1000
  return new Date(parseInt(nS)).toLocaleString().replace(/:\d{1,2}$/, ' ');
}

// deepCompare
export function deepCompare(origin, target) {
  if (typeof target === 'object') {
    if (typeof origin !== 'object') return false;
    for (let key of Object.keys(target)) if (!deepCompare(origin[key], target[key])) return false;
    return true;
  } else return origin === target;
}

// setAllControlToArr
export function setAllControlToArr(allControl) {
  const serviceArray = Object.values(allControl).reduce((a, b) => a.concat(b), []);
  return serviceArray;
}

/**
 * 获取数组对象分页
 * @param {Array} data 数组对象
 * @param {Number} pageIndex 分页索引
 * @param {Number} pageSize 分页大小
 */
export function getArrayPagedData(data, pageIndex, pageSize) {
  let startIdx = (pageIndex - 1) * pageSize;
  let endIdx = startIdx + pageSize;
  let pagedData = [];
  if (endIdx >= data.length) {
    pagedData = data.slice(startIdx, data.length);
  } else {
    pagedData = data.slice(startIdx, endIdx);
  }
  return pagedData;
}

/**
 *
 * @param {Function} callBack 需被节流的函数
 * @param {Number} delay 延迟时间
 * @param {Number} intervalTime 时间间隔
 */
export function thorttleFn(callBack, delay, intervalTime) {
  var timer = null; // 定时器变量
  var time = 0; // 时间变量
  return function() {
    var context = this;
    var curTime = new Date(); // 当前执行的时间
    clearTimeout(timer); //  清除上次的定时器

    if (!time) {
      time = curTime;
    }
    // 当前执行时间距离上次执行的时间是否大于等于间隔时间
    if (curTime - time >= intervalTime) {
      time = curTime;
      callBack.apply(context, arguments);
    } else {
      timer = setTimeout(() => {
        callBack.apply(context, arguments);
      }, delay);
    }
  };
}

/**
 * @description 将拿到的应用数据做处理，放在datamanager和store里面做存储
 * @export
 * @param {Object} appData
 * @returns  不包含数据的组件配置
 */
export function setAppData(appData) {
  const appDataCopy = deepCopy(appData);
  for (const [key, item] of Object.entries(appDataCopy)) {
    if (item.options.data && item.options.data.rows) {
      dataManager.setAppData(key, item.options.data.rows);
      item.options.data.rows = [];
    }
  }
  return appDataCopy;
}

/**
 * @description 整合组件配置
 * @export
 * @param {Object} controls
 * @returns  包含数据的组件配置
 */
export function integrationControl(controls) {
  const controlsCopy = deepCopy(controls);
  for (const [key, value] of Object.entries(controlsCopy)) {
    const resData = dataManager.getComponentData(key);
    if (resData) {
      value.options.data.rows = resData;
    }
  }
  return controlsCopy;
}

/**
 * @description 将组件的位置信息放到外部
 * @export
 * @param {Array} layout
 * @returns 组件配置
 */
export function setPositionToOut(layout) {
  let layoutCopy = deepCopy(layout);
  for (let [key, item] of layout.entries()) {
    layoutCopy[key] = { ...item, ...item.appearance.position };
  }
  return layoutCopy;
}

/**
 * 获取滚动条宽度
 * @param {Boolean} fresh 是否更新缓存
 */
let cached;
export function getScrollBarSize(fresh) {
  if (fresh || cached === undefined) {
    const inner = document.createElement('div');
    inner.style.width = '100%';
    inner.style.height = '200px';

    const outer = document.createElement('div');
    const outerStyle = outer.style;

    outerStyle.position = 'absolute';
    outerStyle.top = 0;
    outerStyle.left = 0;
    outerStyle.pointerEvents = 'none';
    outerStyle.visibility = 'hidden';
    outerStyle.width = '200px';
    outerStyle.height = '150px';
    outerStyle.overflow = 'hidden';

    outer.appendChild(inner);

    document.body.appendChild(outer);

    const widthContained = inner.offsetWidth;
    outer.style.overflow = 'scroll';
    let widthScroll = inner.offsetWidth;

    if (widthContained === widthScroll) {
      widthScroll = outer.clientWidth;
    }

    document.body.removeChild(outer);

    cached = widthContained - widthScroll;
  }
  return cached;
}

/**
 * 移除数组中的指定项
 * @param {Array} array 要移除元素的数组
 * @param {Object} item 要移除的值
 */
export function removeArrayItem(array, item) {
  let index = array.indexOf(item);
  if (index > -1) {
    array.splice(index, 1);
  }
}

/**
 * 移除数组中的指定项
 * @param {Array} array 要移除元素的数组
 * @param {Function} itemFunc 遍历函数
 */
export function removeArrayItemEx(array, itemFunc) {
  let index = -1;
  for (let i = 0; i < array.length; i++) {
    if (itemFunc(array[i])) {
      index = i;
      break;
    }
  }
  if (index > -1) {
    array.splice(index, 1);
  }
}

/**
 * @description
 * @export 返回一串字母+数字的字符串
 * @param {Boolean} randomFlag
 * @param {Number} min
 * @param {Number} max
 * @returns String
 */
export function randomWord(randomFlag, min, max) {
  let str = '',
    range = min,
    arr = [
      '0',
      '1',
      '2',
      '3',
      '4',
      '5',
      '6',
      '7',
      '8',
      '9',
      'a',
      'b',
      'c',
      'd',
      'e',
      'f',
      'g',
      'h',
      'i',
      'j',
      'k',
      'l',
      'm',
      'n',
      'o',
      'p',
      'q',
      'r',
      's',
      't',
      'u',
      'v',
      'w',
      'x',
      'y',
      'z',
      'A',
      'B',
      'C',
      'D',
      'E',
      'F',
      'G',
      'H',
      'I',
      'J',
      'K',
      'L',
      'M',
      'N',
      'O',
      'P',
      'Q',
      'R',
      'S',
      'T',
      'U',
      'V',
      'W',
      'X',
      'Y',
      'Z',
    ];

  // 随机产生
  if (randomFlag) {
    range = Math.round(Math.random() * (max - min)) + min;
  }
  for (let i = 0; i < range; i++) {
    const pos = Math.round(Math.random() * (arr.length - 1));
    str += arr[pos];
  }
  return str;
}

/* 数据类型判断 */
export function nodeType(node) {
  switch (node.typeId) {
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
      return 'directory';
    case '20001': //点线面
    case '20002': //地名地址
    case '20005': //接图表Shapezip
    case '20010': //csv
    case '20011': //csv dataset
    case '20012': //csv zip
    case '20016': //地名地址csvzip
      return 'vector';
    case '20003': //dom tiff
    case '20007': //dom 影像图幅文件
    case '20008': //dem tiff
    case '20009': //dem 影像图幅文件
      return 'raster';
    case '20102': //sld 样式文件
      return 'sld';
    case '10005': //doc
    case '10006': //txt
    case '10007': //csv
    case '10008': //xls
    case '10009': //zip
    case '10010': //pdf
      return 'file';
    case '20099': //第三方服务
      return 'service';
  }
}

export function isDirectory(node) {
  return nodeType(node) === 'directory';
}

export function isVector(node) {
  return nodeType(node) === 'vector';
}

export function isRaster(node) {
  return nodeType(node) === 'raster';
}

export function isSld(node) {
  return nodeType(node) === 'sld';
}

export function isFile(node) {
  return nodeType(node) === 'file';
}

// 第三方服务及gis数据类型
export function isService(node) {
  return nodeType(node) === 'service';
}

//是否是资源
export function isResource(node) {
  return parseInt(node.typeId) > 8;
}

export function isGisResource(node) {
  return isVector(node) || isRaster(node);
}

export function canView(serviceList) {
  return serviceList.length >= 2 || (serviceList.length === 1 && serviceList[0].servicestype === 5);
}

//获取资源图标
export function iconClass(node) {
  switch (node.typeId) {
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
      return node.expand ? 'folder-open' : 'folder';
    case '20001': //点线面
    case '20010': //csv
    case '20011': //csv dataset
    case '20012': //csv zip
      switch (node.shapeType.toUpperCase()) {
        case 'POINT':
          return 'point';
        case 'POLYLINE':
        case 'LINESTRING':
        case 'MULTILINESTRING':
          return 'line';
        case 'POLYGON':
        case 'MULTIPOLYGON':
          return 'polygon';
      }
    case '20002': //地名地址
      return 'dmdz';
    case '20003': //dom tiff
    case '20007': //dom 影像图幅文件
      return 'dom';
    case '20008': //dem tiff
    case '20009': //dem 影像图幅文件
      return 'dem';
    case '20005': //接图表shapezip
      return 'grid';
    case '20014': //controlcsvzip dataset
      return 'point';
    case '10005': //doc
      return 'doc';
    case '10006': //txt
      return 'txt';
    case '10007': //csv
      return 'csv';
    case '10008': //xls
      return 'xls';
    case '10009': //zip
      return 'zip';
    case '10010': //pdf
      return 'pdf';
    default:
      return 'other';
  }
}

/* 时间函数 */
export function getTimeStamp(day = 0) {
  const date = new Date();
  const BASE = 24 * 60 * 60 * 1000;
  const todayTimeStamp = date.getTime() - date.getTime() % BASE;
  return todayTimeStamp - day * BASE;
}

// 样式文件管理
export const styleType = [
  {
    value: ' ',
    label: '全部',
  },
  {
    value: '1',
    label: '点类型',
  },
  {
    value: '2',
    label: '线类型',
  },
  {
    value: '3',
    label: '面类型',
  },
  {
    value: '4',
    label: 'DEM类型',
  },
  {
    value: '0',
    label: '未知类型',
  },
];
export function getStyleType(type) {
  if (type === '') type = ' ';
  const filterStyle = styleType.filter(item => item.value === String(type));
  if (filterStyle.length !== 0) {
    return filterStyle[0].label;
  }
}

//schema保留字段
const reservedFileds = ['geom', 'gid', 'x1', 'y1', 'x2', 'y2', 'Shape_Leng', 'Shape_Area'];

//过滤schema字段，去掉保留字段
export function filterSchema(schemas) {
  let fields = [];
  schemas.forEach(p => {
    if (reservedFileds.indexOf(p) < 0) {
      fields.push(p);
    }
  });
  return fields;
}

export const deleteStatus = [
  {
    value: '200',
    label: '删除成功',
  },
  {
    value: '35271',
    label: '样式被占用',
  },
  {
    value: '400',
    label: '删除失败',
  },
  {
    value: '404',
    label: '样式已被删除',
  },
  {
    value: '403',
    label: '用户信息失效',
  },
  {
    value: '500',
    label: '服务器异常',
  },
];

export function getDelelteStatus(type) {
  const filterStyle = deleteStatus.filter(item => item.value === String(type));
  if (filterStyle.length !== 0) {
    return filterStyle[0].label;
  }
}
